package com.luoboduner.moo.info.ui.dialog;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.formdev.flatlaf.util.StringUtils;
import com.formdev.flatlaf.util.SystemInfo;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import com.intellij.uiDesigner.core.Spacer;
import com.luoboduner.moo.info.App;
import com.luoboduner.moo.info.bean.MonDept;
import com.luoboduner.moo.info.bean.MonEquipType;
import com.luoboduner.moo.info.ui.Init;
import com.luoboduner.moo.info.ui.component.JAutoCompleteComboBox;
import com.luoboduner.moo.info.ui.form.LoadingForm;
import com.luoboduner.moo.info.ui.form.MainWindow;
import com.luoboduner.moo.info.util.ComponentUtil;
import com.luoboduner.moo.info.util.ScrollUtil;
import com.luoboduner.moo.info.util.SystemUtil;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.plaf.FontUIResource;
import javax.swing.text.StyleContext;
import java.awt.*;
import java.awt.event.*;
import java.util.Locale;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class SettingDialog extends JDialog {

  private static final Log logger = LogFactory.get();

  private JPanel loadingPanel;
  private JPanel contentPane;
  private JScrollPane settingScrollPane;
  private JCheckBox autoCheckUpdateCheckBox;
  private JComboBox cbbSubject;
  private JTextField placeText;
  private JTextField equipIdText;
  private JTextField edServerIp;
  private JButton btnSure;
  private JButton btnCancel;
  private JComboBox cbbDept;
  private JPanel panel1;
  private JPanel panel2;
  private JButton btnGetInfo;
  private JTextField edPort;
  private JPanel panel3;
  private ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 40, 2, TimeUnit.MINUTES, new LinkedBlockingDeque<>());

  private java.util.List<MonDept> deptList;

  public SettingDialog() {

    super(App.mainFrame, "参数设置窗口");
    $$$setupUI$$$();
    ComponentUtil.setPreferSizeAndLocateToCenter(this, 0.5, 0.6);
    setContentPane(contentPane);

    loadingPanel = new LoadingForm().getLoadingPanel();
    loadingPanel.setVisible(false);
    contentPane.add(loadingPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));

    setModal(true);

    if (SystemUtil.isMacOs() && SystemInfo.isMacFullWindowContentSupported) {
      this.getRootPane().putClientProperty("apple.awt.fullWindowContent", true);
      this.getRootPane().putClientProperty("apple.awt.transparentTitleBar", true);
      this.getRootPane().putClientProperty("apple.awt.fullscreenable", true);
      this.getRootPane().putClientProperty("apple.awt.windowTitleVisible", false);
      GridLayoutManager gridLayoutManager = (GridLayoutManager) contentPane.getLayout();
      gridLayoutManager.setMargin(new Insets(28, 0, 0, 0));
    }

    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
    addWindowListener(new WindowAdapter() {
      @Override
      public void windowClosing(WindowEvent e) {
        onCancel();
      }
    });

    edPort.addKeyListener(new KeyListener() {
      @Override
      public void keyTyped(KeyEvent e) {
        char c = e.getKeyChar();
        if (!(Character.isDigit(c) || c == KeyEvent.VK_BACK_SPACE)) {
          e.consume(); // 如果输入的不是数字，则取消事件
        }
      }

      @Override
      public void keyPressed(KeyEvent e) {
      }

      @Override
      public void keyReleased(KeyEvent e) {
      }
    });
    // call onCancel() on ESCAPE
    contentPane.registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);

    // Set the scroll bar speed
    ScrollUtil.smoothPane(settingScrollPane);

    // routine
    autoCheckUpdateCheckBox.setSelected(App.config.isAutoCheckUpdate());
    edServerIp.setText(App.config.getServerIp());
    edPort.setText(App.config.getPort());


    if (App.config.getEquipId().isEmpty()) {
      String id = App.si.getHardware().getComputerSystem().getHardwareUUID();
      id = id.replaceAll("-", "").toLowerCase();
      if (StrUtil.isNotBlank(id)) {
        equipIdText.setText(id);
      } else {
        id = App.si.getHardware().getProcessor().getProcessorIdentifier().getProcessorID();
        if (StrUtil.isNotBlank(id)) {
          equipIdText.setText(id.replaceAll("-", "").toLowerCase());
        } else {
          equipIdText.setText(UUID.randomUUID().toString());
        }
      }
    } else {
      equipIdText.setText(App.config.getEquipId());
    }

    placeText.setText(App.config.getAddress());
    contentPane.updateUI();

    btnSure.addActionListener(e -> {
      if (edServerIp.getText().isEmpty()) {
        JOptionPane.showMessageDialog(this, "请输入服务器地址!", "信息",
          JOptionPane.WARNING_MESSAGE);
        return;
      }
      if (edPort.getText().isEmpty()) {
        JOptionPane.showMessageDialog(this, "请输入端口!", "信息",
          JOptionPane.WARNING_MESSAGE);
        return;
      }
      if (cbbDept.getSelectedIndex() == -1) {
        JOptionPane.showMessageDialog(MainWindow.getInstance().getMainPanel(), "请选择学校!", "信息",
          JOptionPane.WARNING_MESSAGE);
        return;
      }
      if (cbbSubject.getSelectedIndex() == -1) {
        JOptionPane.showMessageDialog(MainWindow.getInstance().getMainPanel(), "请选择设备类型!", "信息",
          JOptionPane.WARNING_MESSAGE);
        return;
      }
      App.config.setAutoCheckUpdate(autoCheckUpdateCheckBox.isSelected());
      App.config.setServerIp(edServerIp.getText());
      App.config.setPort(edPort.getText());
      App.config.setEquipId(equipIdText.getText());
      App.config.setAddress(placeText.getText());
      App.config.setDeptId(deptList.get(cbbDept.getSelectedIndex()).getDeptId().toString());
      App.config.setSubjectId(Init.deptAppList.getMonEquipTypeList().get(cbbSubject.getSelectedIndex()).getStandardId());
      App.config.setSubjectName(Objects.requireNonNull(cbbSubject.getSelectedItem()).toString());
      App.config.setFreq(Init.deptAppList.getFreq());

      loadingPanel.setVisible(true);
      contentPane.setEnabled(false);
      contentPane.updateUI();

      showWaitingPanel(true);
      Runnable runnable = () -> {
        try {
          App.config.save();
          Init.uploadSubjectInfo(true);
          onCancel();
        } catch (Exception e1) {
          JOptionPane.showMessageDialog(this, "提交出错，原因：" + e1.getMessage(), "出错",
            JOptionPane.WARNING_MESSAGE);
        } finally {
          showWaitingPanel(false);
        }

      };
      executor.execute(runnable);
    });
    btnCancel.addActionListener(e -> onCancel());
    btnGetInfo.addActionListener(e -> {
      App.config.setServerIp(edServerIp.getText());
      App.config.setPort(edPort.getText());
      loadData();
    });
    loadData();
  }


  private void showWaitingPanel(boolean isShow) {
    loadingPanel.setVisible(isShow);
    btnSure.setEnabled(!isShow);
    btnCancel.setEnabled(!isShow);
    contentPane.updateUI();

  }


  private void onCancel() {
    // add your code here
    dispose();
    if (!Init.configSucceed()) {
      System.exit(1);
    }
  }

  private void loadData() {

    if (StrUtil.isBlank(App.config.getServerIp()) || StrUtil.isBlank(App.config.getPort())) {
      return;
    }

    showWaitingPanel(true);

    Runnable runnable = () -> {

      try {
        Init.getDeptEquipAppList();
        if (ObjectUtil.isNotEmpty(Init.deptAppList)) {
          deptList = Init.deptAppList.getDeptList();
          deptList.forEach(dept -> {
            cbbDept.addItem(dept.getDeptName());
          });

          if (StrUtil.isBlank(App.config.getDeptId()) && ObjectUtil.isNotEmpty(Init.deptAppList.getDeptId())) {
            App.config.setDeptId(Init.deptAppList.getDeptId() + "");
          }
          if (StrUtil.isBlank(App.config.getSubjectId()) && StrUtil.isNotEmpty(Init.deptAppList.getEquipTypeId())) {
            App.config.setSubjectId(Init.deptAppList.getEquipTypeId());
          }
          if (StrUtil.isBlank(App.config.getAddress()) && StrUtil.isNotEmpty(Init.deptAppList.getAddress())) {
            App.config.setAddress(Init.deptAppList.getAddress());
          }

          if (App.config.getDeptId().isEmpty()) {
            cbbDept.setSelectedIndex(-1);
          }
          else {
            MonDept dept = deptList.stream().filter(obj ->
              obj.getDeptId() == Integer.parseInt(App.config.getDeptId())).findFirst().orElse(null);
            cbbDept.setSelectedIndex(deptList.indexOf(dept));
          }


          Init.deptAppList.getMonEquipTypeList().forEach(equipType -> {
            cbbSubject.addItem(equipType.getObjName());
          });

          if (App.config.getSubjectId().isEmpty()) {
            cbbSubject.setSelectedIndex(-1);
          }
          else {
            MonEquipType equipType = Init.deptAppList.getMonEquipTypeList().stream().filter(obj ->
              Objects.equals(obj.getStandardId(), App.config.getSubjectId())).findFirst().orElse(null);
            cbbSubject.setSelectedIndex(Init.deptAppList.getMonEquipTypeList().indexOf(equipType));
          }
          if (StrUtil.isNotBlank(App.config.getAddress())) {
            placeText.setText(App.config.getAddress());
          }

        }
        else {
          JOptionPane.showMessageDialog(this, "获取信息失败，请检查服务器地址是否正确!", "信息",
            JOptionPane.WARNING_MESSAGE);
        }
      } catch (Exception e) {
        showWaitingPanel(false);
        JOptionPane.showMessageDialog(this, "获取信息失败，请检查服务器地址是否正确!", "信息",
          JOptionPane.WARNING_MESSAGE);
      } finally {
        showWaitingPanel(false);
      }
    };
    executor.execute(runnable);

  }

  /**
   * Method generated by IntelliJ IDEA GUI Designer
   * >>> IMPORTANT!! <<<
   * DO NOT edit this method OR call it in your code!
   *
   * @noinspection ALL
   */
  private void $$$setupUI$$$() {
    createUIComponents();
    contentPane = new JPanel();
    contentPane.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
    contentPane.setEnabled(true);
    contentPane.setFocusable(true);
    settingScrollPane = new JScrollPane();
    contentPane.add(settingScrollPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
    settingScrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
    panel1.setLayout(new GridLayoutManager(5, 3, new Insets(20, 20, 10, 10), -1, -1));
    settingScrollPane.setViewportView(panel1);
    final JPanel panel4 = new JPanel();
    panel4.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
    panel1.add(panel4, new GridConstraints(0, 0, 2, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(600, -1), null, 0, false));
    panel2 = new JPanel();
    panel2.setLayout(new GridLayoutManager(7, 5, new Insets(15, 15, 25, 0), -1, 12));
    panel4.add(panel2, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
    panel2.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, this.$$$getFont$$$(null, Font.BOLD, -1, panel2.getFont()), new Color(-2104859)));
    final JLabel label1 = new JLabel();
    label1.setText("设备编码");
    panel2.add(label1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
    final JLabel label2 = new JLabel();
    label2.setText("学校");
    panel2.add(label2, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
    final JLabel label3 = new JLabel();
    label3.setText("类型");
    panel2.add(label3, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
    cbbSubject = new JComboBox();
    panel2.add(cbbSubject, new GridConstraints(3, 1, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
    final JLabel label4 = new JLabel();
    label4.setText("放置位置");
    panel2.add(label4, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
    placeText = new JTextField();
    panel2.add(placeText, new GridConstraints(4, 1, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
    equipIdText = new JTextField();
    equipIdText.setEditable(false);
    equipIdText.setEnabled(false);
    panel2.add(equipIdText, new GridConstraints(1, 1, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
    autoCheckUpdateCheckBox = new JCheckBox();
    autoCheckUpdateCheckBox.setText("自动检查更新");
    panel2.add(autoCheckUpdateCheckBox, new GridConstraints(5, 0, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
    final JLabel label5 = new JLabel();
    label5.setText("服务器地址");
    panel2.add(label5, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
    edServerIp = new JTextField();
    panel2.add(edServerIp, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, new Dimension(260, -1), new Dimension(150, -1), null, 0, false));
    panel2.add(cbbDept, new GridConstraints(2, 1, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
    btnGetInfo = new JButton();
    btnGetInfo.setText("获取信息");
    panel2.add(btnGetInfo, new GridConstraints(0, 4, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
    final JLabel label6 = new JLabel();
    label6.setText("端口");
    panel2.add(label6, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
    edPort = new JTextField();
    panel2.add(edPort, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), new Dimension(100, -1), 0, false));
    final Spacer spacer1 = new Spacer();
    panel1.add(spacer1, new GridConstraints(1, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
    final Spacer spacer2 = new Spacer();
    panel1.add(spacer2, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
    final JPanel panel5 = new JPanel();
    panel5.setLayout(new GridLayoutManager(1, 3, new Insets(0, 0, 0, 0), -1, -1));
    panel1.add(panel5, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_NORTH, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false));
    btnCancel = new JButton();
    btnCancel.setText("放弃");
    panel5.add(btnCancel, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
    btnSure = new JButton();
    btnSure.setEnabled(true);
    btnSure.setText("确定");
    panel5.add(btnSure, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_EAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
    final Spacer spacer3 = new Spacer();
    panel5.add(spacer3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
    final Spacer spacer4 = new Spacer();
    panel1.add(spacer4, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
  }

  /**
   * @noinspection ALL
   */
  private Font $$$getFont$$$(String fontName, int style, int size, Font currentFont) {
    if (currentFont == null) return null;
    String resultName;
    if (fontName == null) {
      resultName = currentFont.getName();
    }
    else {
      Font testFont = new Font(fontName, Font.PLAIN, 10);
      if (testFont.canDisplay('a') && testFont.canDisplay('1')) {
        resultName = fontName;
      }
      else {
        resultName = currentFont.getName();
      }
    }
    Font font = new Font(resultName, style >= 0 ? style : currentFont.getStyle(), size >= 0 ? size : currentFont.getSize());
    boolean isMac = System.getProperty("os.name", "").toLowerCase(Locale.ENGLISH).startsWith("mac");
    Font fontWithFallback = isMac ? new Font(font.getFamily(), font.getStyle(), font.getSize()) : new StyleContext().getFont(font.getFamily(), font.getStyle(), font.getSize());
    return fontWithFallback instanceof FontUIResource ? fontWithFallback : new FontUIResource(fontWithFallback);
  }

  /**
   * @noinspection ALL
   */
  public JComponent $$$getRootComponent$$$() {
    return contentPane;
  }

  private void createUIComponents() {
    panel1 = new JPanel();

    panel3 = new JPanel();

    cbbDept = new JAutoCompleteComboBox();
  }
}
